package com.slink.fxfk.framework.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

/**
 * 图片工具类， 图片水印，文字水印，缩放，补白等
 * 
 */
public class ImageUtil
{
	public static Map<String, String> IMG_FILE_TYPE_MAP = new HashMap<String, String>();

	static {
		IMG_FILE_TYPE_MAP.put("jpg", "FFD8FF"); // JPEG (jpg)
		IMG_FILE_TYPE_MAP.put("png", "89504E47"); // PNG (png)
		IMG_FILE_TYPE_MAP.put("gif", "47494638"); // GIF (gif)
		IMG_FILE_TYPE_MAP.put("bmp", "424D"); // Windows Bitmap (bmp)
		IMG_FILE_TYPE_MAP.put("png", "89504E470D0a1a0a0000"); // PNG (png)
		IMG_FILE_TYPE_MAP.put("bmp", "424d228c010000000000"); // 16色位图(bmp)
		IMG_FILE_TYPE_MAP.put("bmp", "424d8240090000000000"); // 24位位图(bmp)
		IMG_FILE_TYPE_MAP.put("bmp", "424d8e1b030000000000"); // 256色位图(bmp
	}

	/**
	 * FILE_TYPE_MAP.put("ffd8ffe000104a464946", "jpg"); //JPEG (jpg)
	 * FILE_TYPE_MAP.put("89504e470d0a1a0a0000", "png"); //PNG (png)
	 * FILE_TYPE_MAP.put("47494638396126026f01", "gif"); //GIF (gif)
	 * FILE_TYPE_MAP.put("49492a00227105008037", "tif"); //TIFF (tif)
	 * FILE_TYPE_MAP.put("424d228c010000000000", "bmp"); //16色位图(bmp)
	 * FILE_TYPE_MAP.put("424d8240090000000000", "bmp"); //24位位图(bmp)
	 * FILE_TYPE_MAP.put("424d8e1b030000000000", "bmp"); //256色位图(bmp)
	 * FILE_TYPE_MAP.put("41433130313500000000", "dwg"); //CAD (dwg)
	 * FILE_TYPE_MAP.put("3c21444f435459504520", "html"); //HTML (html)
	 * FILE_TYPE_MAP.put("3c21646f637479706520", "htm"); //HTM (htm)
	 * FILE_TYPE_MAP.put("48544d4c207b0d0a0942", "css"); //css
	 * FILE_TYPE_MAP.put("696b2e71623d696b2e71", "js"); //js
	 * FILE_TYPE_MAP.put("7b5c727466315c616e73", "rtf"); //Rich Text Format
	 * (rtf) FILE_TYPE_MAP.put("38425053000100000000", "psd"); //Photoshop (psd)
	 * FILE_TYPE_MAP.put("46726f6d3a203d3f6762", "eml"); //Email [Outlook
	 * Express 6] (eml) FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "doc"); //MS
	 * Excel 注意：word、msi 和 excel的文件头一样 FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000",
	 * "vsd"); //Visio 绘图 FILE_TYPE_MAP.put("5374616E64617264204A", "mdb"); //MS
	 * Access (mdb) FILE_TYPE_MAP.put("252150532D41646F6265", "ps");
	 * FILE_TYPE_MAP.put("255044462d312e350d0a", "pdf"); //AdobeAcrobat (pdf)
	 * FILE_TYPE_MAP.put("2e524d46000000120001", "rmvb"); //rmvb/rm相同
	 * FILE_TYPE_MAP.put("464c5601050000000900", "flv"); //flv与f4v相同
	 * FILE_TYPE_MAP.put("00000020667479706d70", "mp4");
	 * FILE_TYPE_MAP.put("49443303000000002176", "mp3");
	 * FILE_TYPE_MAP.put("000001ba210001000180", "mpg"); //
	 * FILE_TYPE_MAP.put("3026b2758e66cf11a6d9", "wmv"); //wmv与asf相同
	 * FILE_TYPE_MAP.put("52494646e27807005741", "wav"); //Wave (wav)
	 * FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
	 * FILE_TYPE_MAP.put("4d546864000000060001", "mid"); //MIDI (mid)
	 * FILE_TYPE_MAP.put("504b0304140000000800", "zip");
	 * FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");
	 * FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
	 * FILE_TYPE_MAP.put("504b03040a0000000000", "jar");
	 * FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");//可执行文件
	 * FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");//jsp文件
	 * FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");//MF文件
	 * FILE_TYPE_MAP.put("3c3f786d6c2076657273", "xml");//xml文件
	 * FILE_TYPE_MAP.put("494e5345525420494e54", "sql");//xml文件
	 * FILE_TYPE_MAP.put("7061636b616765207765", "java");//java文件
	 * FILE_TYPE_MAP.put("406563686f206f66660d", "bat");//bat文件
	 * FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");//gz文件
	 * FILE_TYPE_MAP.put("6c6f67346a2e726f6f74", "properties");//bat文件
	 * FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");//bat文件
	 * FILE_TYPE_MAP.put("49545346030000006000", "chm");//bat文件
	 * FILE_TYPE_MAP.put("04000000010000001300", "mxp");//bat文件
	 * FILE_TYPE_MAP.put("504b0304140006000800", "docx");//docx文件
	 * FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000",
	 * "wps");//WPS文字wps、表格et、演示dps都是一样的
	 * FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
	 * 
	 * 
	 * FILE_TYPE_MAP.put("6D6F6F76", "mov"); //Quicktime (mov)
	 * FILE_TYPE_MAP.put("FF575043", "wpd"); //WordPerfect (wpd)
	 * FILE_TYPE_MAP.put("CFAD12FEC5FD746F", "dbx"); //Outlook Express (dbx)
	 * FILE_TYPE_MAP.put("2142444E", "pst"); //Outlook (pst)
	 * FILE_TYPE_MAP.put("AC9EBD8F", "qdf"); //Quicken (qdf)
	 * FILE_TYPE_MAP.put("E3828596", "pwl"); //Windows Password (pwl)
	 * FILE_TYPE_MAP.put("2E7261FD", "ram"); //Real Audio (ram)
	 **/

	/**
	 * 判断是否是图片文件
	 * 
	 * @param b
	 * @return
	 * @throws IOException
	 */
	public static Boolean isImgFile(InputStream input)
	{
		Boolean blen = false;
		ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
		for (int i = 0; i < 10; i++) {
			int a = 0;
			try {
				a = input.read();
			}
			catch (IOException e) {
				return false;
			}
			bytestream.write(a);
		}
		byte head[] = bytestream.toByteArray();

		String filetypeHex = String.valueOf(getFileHexString(head));
		Iterator<Entry<String, String>> entryiterator = IMG_FILE_TYPE_MAP.entrySet().iterator();
		while (entryiterator.hasNext()) {
			Entry<String, String> entry = entryiterator.next();
			String fileTypeHexValue = entry.getValue().toUpperCase();
			if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
				return true;
			}
		}
		return blen;
	}

	public static String getFileHexString(byte[] b)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (b == null || b.length <= 0) {
			return null;
		}
		for (int i = 0; i < b.length; i++) {
			int v = b[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	/** 图片格式：JPG */
	private static final String PICTRUE_FORMATE_JPG = "jpg";

	/**
	 * 添加图片水印
	 * 
	 * @param targetImg
	 *            目标图片路径，如：C://myPictrue//1.jpg
	 * @param waterImg
	 *            水印图片路径，如：C://myPictrue//logo.png
	 * @param x
	 *            水印图片距离目标图片左侧的偏移量，如果x<0, 则在正中间
	 * @param y
	 *            水印图片距离目标图片上侧的偏移量，如果y<0, 则在正中间
	 * @param alpha
	 *            透明度(0.0 -- 1.0, 0.0为完全透明，1.0为完全不透明)
	 */
	public static void pressImage(String targetImg, String waterImg, int x, int y, float alpha)
	{
		try {
			File file = new File(targetImg);
			Image image = ImageIO.read(file);
			int width = image.getWidth(null);
			int height = image.getHeight(null);
			BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = bufferedImage.createGraphics();
			g.drawImage(image, 0, 0, width, height, null);

			Image waterImage = ImageIO.read(new File(waterImg)); // 水印文件
			int width_1 = waterImage.getWidth(null);
			int height_1 = waterImage.getHeight(null);
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

			int widthDiff = width - width_1;
			int heightDiff = height - height_1;
			if (x < 0) {
				x = widthDiff / 2;
			}
			else if (x > widthDiff) {
				x = widthDiff;
			}
			if (y < 0) {
				y = heightDiff / 2;
			}
			else if (y > heightDiff) {
				y = heightDiff;
			}
			g.drawImage(waterImage, x, y, width_1, height_1, null); // 水印文件结束
			g.dispose();
			ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 添加文字水印
	 * 
	 * @param targetImg
	 *            目标图片路径，如：C://myPictrue//1.jpg
	 * @param pressText
	 *            水印文字， 如：中国证券网
	 * @param fontName
	 *            字体名称， 如：宋体
	 * @param fontStyle
	 *            字体样式，如：粗体和斜体(Font.BOLD|Font.ITALIC)
	 * @param fontSize
	 *            字体大小，单位为像素
	 * @param color
	 *            字体颜色
	 * @param x
	 *            水印文字距离目标图片左侧的偏移量，如果x<0, 则在正中间
	 * @param y
	 *            水印文字距离目标图片上侧的偏移量，如果y<0, 则在正中间
	 * @param alpha
	 *            透明度(0.0 -- 1.0, 0.0为完全透明，1.0为完全不透明)
	 */
	public static void pressText(String targetImg, String pressText, String fontName, int fontStyle, int fontSize, Color color, int x, int y,
			float alpha)
	{
		try {
			File file = new File(targetImg);

			Image image = ImageIO.read(file);
			int width = image.getWidth(null);
			int height = image.getHeight(null);
			BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = bufferedImage.createGraphics();
			g.drawImage(image, 0, 0, width, height, null);
			g.setFont(new Font(fontName, fontStyle, fontSize));
			g.setColor(color);
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

			int width_1 = fontSize * getLength(pressText);
			int height_1 = fontSize;
			int widthDiff = width - width_1;
			int heightDiff = height - height_1;
			if (x < 0) {
				x = widthDiff / 2;
			}
			else if (x > widthDiff) {
				x = widthDiff;
			}
			if (y < 0) {
				y = heightDiff / 2;
			}
			else if (y > heightDiff) {
				y = heightDiff;
			}

			g.drawString(pressText, x, y + height_1);
			g.dispose();
			ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取字符长度，一个汉字作为 1 个字符, 一个英文字母作为 0.5 个字符
	 * 
	 * @param text
	 * @return 字符长度，如：text="中国",返回 2；text="test",返回 2；text="中国ABC",返回 4.
	 */
	public static int getLength(String text)
	{
		int textLength = text.length();
		int length = textLength;
		for (int i = 0; i < textLength; i++) {
			if (String.valueOf(text.charAt(i)).getBytes().length > 1) {
				length++;
			}
		}
		return (length % 2 == 0) ? length / 2 : length / 2 + 1;
	}

	/**
	 * 图片缩放
	 * 
	 * @param filePath
	 *            图片路径
	 * @param height
	 *            高度
	 * @param width
	 *            宽度
	 * @param bb
	 *            比例不对时是否需要补白
	 * @throws IOException 
	 */
	public static void resize(String filePath, int height, int width, boolean bb) throws IOException
	{
		double ratio = 0; // 缩放比例
		File f = new File(filePath);
		BufferedImage bi = ImageIO.read(f);
		int h = bi.getHeight();
		int w = bi.getWidth();
		height = h > height ? height : h;
		width = w > width ? width : w;
		Image itemp = bi.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
		// 计算比例
		if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
			if (bi.getHeight() > bi.getWidth()) {
				ratio = (new Integer(height)).doubleValue() / bi.getHeight();
			}
			else {
				ratio = (new Integer(width)).doubleValue() / bi.getWidth();
			}
			AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
			itemp = op.filter(bi, null);
			
			if (bb) {
				BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
				Graphics2D g = image.createGraphics();
				g.setColor(Color.white);
				g.fillRect(0, 0, width, height);
				if (width == itemp.getWidth(null))
					g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null), itemp.getHeight(null), Color.white, null);
				else
					g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null), itemp.getHeight(null), Color.white, null);
				g.dispose();
				itemp = image;
			}
			ImageIO.write((BufferedImage) itemp, "jpg", f);
		}
	}
	
	// 以下4个为获取文件后缀名和文件名
	public static String getExtension(File f)
	{
		return (f != null) ? getExtension(f.getName()) : "";
	}

	public static String getExtension(String filename)
	{
		return getExtension(filename, "");
	}
	
	public static String getExtension(String filename, String defExt)
	{
		if ((filename != null) && (filename.length() > 0)) {
			int i = filename.lastIndexOf('.');

			if ((i > -1) && (i < (filename.length() - 1))) {
				return filename.substring(i + 1);
			}
		}
		return defExt;
	}

	public static String trimExtension(String filename)
	{
		if ((filename != null) && (filename.length() > 0)) {
			int i = filename.lastIndexOf('.');
			if ((i > -1) && (i < (filename.length()))) {
				return filename.substring(0, i);
			}
		}
		return filename;
	}

	// 图片裁剪
	public static boolean cutTo(String oldFileUrl, String newFileUrl, int selectorX, int selectorY, int imageX, int imageY, int viewPortW,
			int viewPortH, int imageW, int imageH, int selectorW, int selectorH)
	{
		if (imageH < selectorH || imageW < selectorW) {
			// 如果源图片的宽度或高度小于目标图片的宽度或高度，则直接返回出错
			return false;
		}
		try {
			File img = new File(oldFileUrl);
			File fileDest = new File(newFileUrl);
			if (!fileDest.getParentFile().exists())
				fileDest.getParentFile().mkdirs();
			String ext = getExtension(newFileUrl).toLowerCase();
			BufferedImage bi = (BufferedImage) ImageIO.read(img);
			int srcH = bi.getHeight();// 原图高
			int srcw = bi.getWidth();// 原图宽

			// 缩放源图
			if (srcH != imageH || srcw != imageW) {
				BufferedImage tagImage = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB); // 缩放图像
				Image image = bi.getScaledInstance(imageW, imageH, Image.SCALE_SMOOTH);
				Graphics g = tagImage.getGraphics();
				g.drawImage(image, 0, 0, null); // 绘制目标图
				g.dispose();
				bi = tagImage;
			}
			// 剪切
			int cutX = 0, cutY = 0;
			cutX = Math.abs(imageX - selectorX);
			cutY = Math.abs(imageY - selectorY);
			BufferedImage bi_cropper = bi.getSubimage(cutX, cutY, selectorW, selectorH);
			return ImageIO.write(bi_cropper, ext.equals("png") ? "png" : "jpeg", fileDest);
		}
		catch (IOException e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 
	 * 对图片裁剪，并把裁剪完的新图片保存 。
	 * 
	 * @param oldFileUrl
	 *            原图片路径
	 * @param newFileUrl
	 *            新图片路径
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 * @param w
	 *            宽度
	 * @param h
	 *            高度
	 * @throws IOException 
	 */
	public static boolean cut(String oldFileUrl, String newFileUrl, Integer x, Integer y, Integer w, Integer h) throws IOException
	{
		File img = new File(oldFileUrl);
		File fileDest = new File(newFileUrl);
		if (!fileDest.getParentFile().exists())
			fileDest.getParentFile().mkdirs();
		String ext = getExtension(newFileUrl).toLowerCase();
		BufferedImage bi = (BufferedImage) ImageIO.read(img);

		int h1 = Math.min(h, bi.getHeight());
		int w1 = Math.min(w, bi.getWidth());
		if (h1 <= 0)
			h1 = bi.getHeight();
		if (w1 <= 0)
			w1 = bi.getWidth();
		int y1 = Math.min(Math.max(0, y), bi.getHeight() - h1);
		int x1 = Math.min(Math.max(0, x), bi.getWidth() - w1);

		BufferedImage bi_cropper = bi.getSubimage(x1, y1, w1, h1);
		return ImageIO.write(bi_cropper, ext.equals("png") ? "png" : "jpeg", fileDest);

	}
	
	/**
	 * 对图片裁剪
	 * 
	 * @param file
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 * @return
	 * @throws IOException
	 */
	public static boolean cut(File file, Integer x, Integer y, Integer w, Integer h) throws IOException
	{
		BufferedImage bi = (BufferedImage) ImageIO.read(file);
		int h1 = Math.min(h, bi.getHeight());
		int w1 = Math.min(w, bi.getWidth());
		if (h1 <= 0)
			h1 = bi.getHeight();
		if (w1 <= 0)
			w1 = bi.getWidth();
		int y1 = Math.min(Math.max(0, y), bi.getHeight() - h1);
		int x1 = Math.min(Math.max(0, x), bi.getWidth() - w1);
		
		bi.getSubimage(x1, y1, w1, h1);
		return ImageIO.write(bi.getSubimage(x1, y1, w1, h1), "jpeg", file);
	}
}
